#ifndef CODE_GENERATOR_H
#define CODE_GENERATOR_H

#include <string>
#include <vector>
#include <memory>

#define STRUCT_TYPE_MESSAGE     "message"
#define STRUCT_TYPE_ONEOF       "oneof"
#define STRUCT_TYPE_ENUM        "enum"

#define CODE_INDENTATION        "    "
#define DOUBLE_CODE_INDENTATION "        "

namespace pp
{
    class FieldInfo
    {
    private:
        std::string m_sName;        // 字段名
        std::string m_sTag;         // 字段标签
        std::string m_sType;        // 字段类型
        std::string m_sSubType;     // 数组字段子类型
        std::string m_sValue;       // 字段的值，比如常量字段、枚举字段会有个值
        std::string m_sDefault;     // 默认值
        std::string m_sDesc;        // 字段说明/注释
        std::string m_sSize;        // 数组字段最大元素个数
        std::string m_sJsonName;    // json name
        std::string m_sJsonOmitEmpty;// json omit empty
    public:
        FieldInfo(const std::string& name, const std::string& tag, const std::string& ftype,
            const std::string& subtype = "", const std::string& value = "", const std::string& def = "",
            const std::string& desc = "", const std::string& size = "", const std::string& jsonName = "",
            const std::string& jsonOmitEmpty = "");

        void SetName(const std::string& name) {m_sName = name;}
        const std::string& GetName() const {return m_sName;}
        void SetTag(const std::string& tag) {m_sTag = tag;}
        const std::string& GetTag() const {return m_sTag;}
        void SetType(const std::string& ttype) {m_sType = ttype;}
        const std::string& GetType() const {return m_sType;}
        void SetSubType(const std::string& subtype) {m_sSubType = subtype;}
        const std::string& GetSubType() const {return m_sSubType;}
        void SetValue(const std::string& value) {m_sValue = value;}
        const std::string& GetValue() const {return m_sValue;}
        void SetDefault(const std::string& def) {m_sDefault = def;}
        const std::string& GetDefault() const {return m_sDefault;}
        void SetDesc(const std::string& desc) {m_sDesc = desc;}
        const std::string& GetDesc() const {return m_sDesc;}
        void SetSize(const std::string& size) {m_sSize = size;}
        const std::string& GetSize() const {return m_sSize;}
        void SetJsonName(const std::string& jsonName) {m_sJsonName = jsonName;}
        const std::string& GetJsonName() const {return m_sJsonName;}
        void SetJsonOmitEmpty(const std::string& omitEmpty) {m_sJsonOmitEmpty = omitEmpty;}
        const std::string& GetJsonOmitEmpty() const {return m_sJsonOmitEmpty;}
    };

    class StructInfo
    {
    private:
        std::string m_sName;        // 结构体名
        std::string m_sType;        // 结构体类型：struct/message，union/oneof，enum (注意struct与message等价，union与oneof等价)
        std::string m_sDesc;        // 结构体说明/注释
        std::vector<std::shared_ptr<FieldInfo> > m_oFields;     // 本结构体包含的所有子字段
    public:
        StructInfo(const std::string& name, const std::string& stype, const std::string& desc = "");

        void SetName(const std::string& name) {m_sName = name;}
        const std::string& GetName() const {return m_sName;}
        const std::string& GetName() {return m_sName;}
        void SetType(const std::string& stype) {m_sType = stype;}
        const std::string& GetType() const {return m_sType;}
        const std::string& GetType() {return m_sType;}
        void SetDesc(const std::string& desc) {m_sDesc = desc;}
        const std::string& GetDesc() const {return m_sDesc;}
        const std::string& GetDesc() {return m_sDesc;}

        void AddField(std::shared_ptr<FieldInfo>& field) {m_oFields.push_back(field);}
        const std::vector<std::shared_ptr<FieldInfo> >& GetFields() const {return m_oFields;}
    };

    class CodeGenerator
    {
    protected:
        std::string m_sSrcDir;                                  // 协议文件搜索路径
        std::string m_sOutDir;                                  // 文件输出路径
        std::string m_sSrcFile;                                 // 协议文件名
        std::vector<std::string> m_oImports;                    // 导入的头文件
        std::string m_sPackage;                                 // 定义的package
        std::vector<std::shared_ptr<FieldInfo> > m_oConsts;     // 常量
        std::vector<std::shared_ptr<StructInfo> > m_oEnums;     // 枚举
        std::vector<std::shared_ptr<StructInfo> > m_oStructs;   // 结构体
    public:
        CodeGenerator(const std::string& srcdir, const std::string& outdir) : m_sSrcDir(srcdir), m_sOutDir(outdir) {}
    public:
        // 重置数据
        virtual void Reset(const std::string& srcfile); // srcfile是pp定义文件名
        // 处理pp文件中的import定义
        virtual void HandleImport(const std::string& imports);
        // 处理pp文件中的package定义
        virtual void HandlePackage(const std::string& package);
        // 处理pp文件中的option定义，忽略不支持的option。比如option go_package是一个option
        virtual void HandleOption(const std::string& name, const std::string& value);
        // 处理pp文件中的常量定义
        virtual void HandleConst(const std::shared_ptr<FieldInfo>& fieldInfo);
        // 处理pp文件中的enum定义
        virtual void HandleEnum(const std::shared_ptr<StructInfo>& structInfo);
        // 处理pp文件中的message定义
        virtual void HandleStruct(const std::shared_ptr<StructInfo>& structInfo);
        // 生成文件
        virtual void Generate() = 0;
    protected:
        const std::string& GetPackage() const {return m_sPackage;}
        const std::vector<std::shared_ptr<StructInfo> > GetEnums() const {return m_oEnums;}
        const std::vector<std::shared_ptr<StructInfo> > GetStructs() const {return m_oStructs;}
    };
};

#endif
